package com.huawei.esdk.tp.southcommu;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.cxf.common.util.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.huawei.esdk.platform.common.MessageContext;
import com.huawei.esdk.platform.common.ThreadLocalHolder;
import com.huawei.esdk.platform.common.bean.commu.BaseJsonBean;
import com.huawei.esdk.platform.common.bean.log.InterfaceLogBean;
import com.huawei.esdk.platform.common.constants.ESDKErrorCodeConstant;
import com.huawei.esdk.platform.common.utils.ApplicationContextUtil;
import com.huawei.esdk.platform.common.utils.OSUtils;
import com.huawei.esdk.platform.commu.itf.AbstractProtocolAdatperCustProvider;
import com.huawei.esdk.platform.exception.ProtocolAdapterException;
import com.huawei.esdk.platform.log.itf.IInterfaceLog;
import com.huawei.esdk.tp.bean.terminal.ResBean;
import com.huawei.esdk.tp.common.constants.InfoKeys;

public class TPJsonOverHttpCustProvider extends AbstractProtocolAdatperCustProvider
{
    private static final Logger LOGGER = Logger.getLogger(TPJsonOverHttpCustProvider.class);
    
    @Override
    public Object preProcessReq(Object reqMessage)
    {
        if (!(reqMessage instanceof BaseJsonBean))
        {
            throw new IllegalArgumentException("The input parameter reqMessage is not instance of BaseJsonBean");
        }
        
        return reqMessage;
    }

    @Override
    public Map<String, String> getRequestHeaders()
    {
        Map<String, String> headers = new HashMap<String, String>();
        // Prepare the session ID for adding into HTTP header
        String sessionId = null;
        MessageContext mc = ThreadLocalHolder.get();
        if (mc != null)
        {
            sessionId = (String) mc.getEntities().get(InfoKeys.TERMINAL_SESSION_ID.toString());
        }
        if (sessionId != null)
        {
            headers.put("SessionID", sessionId);
        }

        return headers;
    }

    @Override
    public String getContent4Sending(Object reqMessage)
    {
        Gson gson = new Gson();
        String reqPayloadInJSON = gson.toJson(reqMessage);
        return reqPayloadInJSON;
    }

    @Override
    public Object preSend(Object reqMessage)
    {
        return reqMessage;        
    }

    @Override
    public String reBuildNewUrl(String url, String interfaceName)
    {
        String uuid = UUID.randomUUID().toString();
        
        MessageContext mc = ThreadLocalHolder.get();
        if (null != mc)
        {
            mc.getEntities().put("interfaceLogger-TransactionId", uuid);
        }
        
        String targetIP = url;
        try
        {
            URI uri = new URI(url);
            targetIP = uri.getHost();
        }
        catch (URISyntaxException e)
        {
            e.printStackTrace();
        }
        
        InterfaceLogBean bean = new InterfaceLogBean();
        bean.setTransactionId(uuid);
        bean.setProduct("TP");
        bean.setInterfaceType("2");
        bean.setProtocolType("HTTP");
        bean.setReq(true);
        bean.setName(interfaceName);
        bean.setSourceAddr(OSUtils.getLocalIP());
        bean.setTargetAddr(targetIP);
        bean.setReqTime(new Date());
        
        IInterfaceLog logger = ApplicationContextUtil.getBean("interfaceLogger");
        logger.info(bean);
        
        
        return url + "?ActionID=" + interfaceName;
    }

    @Override
    public Object postSend(Object resMessage)
    {
        
        HttpResponse response = (HttpResponse) resMessage;
        String sessionId = null;
        Header[] hs = response.getAllHeaders();
        for (Header header : hs)
        {
            if ("Set-Cookie".equals(header.getName()))
            {
                sessionId = header.getValue().split("=")[1];
                break;
            }
        }

        MessageContext mc = ThreadLocalHolder.get();
        if (mc == null)
        {
            mc = new MessageContext();
        }
        if (null != sessionId)
        {
            mc.getEntities().put(InfoKeys.TERMINAL_SESSION_ID.toString(), sessionId);
        }
        
        return resMessage;
    }

    @Override
    public Object postBuildRes(Object resMessage, String resObjClass) throws ProtocolAdapterException
    {
        Object resObj = null;
        Gson gson = new Gson();
        try
        {
            resObj = gson
                    .fromJson((String)resMessage, Class.forName(ResBean.class.getName()));
        }
        catch (JsonSyntaxException e)
        {
            LOGGER.error("", e);
            throw new ProtocolAdapterException("syncSendMessage error", e, ESDKErrorCodeConstant.ERROR_CODE_SYS_ERROR);
        }
        catch (ClassNotFoundException e)
        {
            LOGGER.error("", e);
            throw new ProtocolAdapterException("syncSendMessage error", e, ESDKErrorCodeConstant.ERROR_CODE_SYS_ERROR);
        }
        
        ResBean resBean = (ResBean) resObj;
        if (null != resBean && resBean.getSuccess() == 1)
        {
            BaseJsonBean dataBean = null;
            try
            {
                dataBean = (BaseJsonBean) gson.fromJson(resBean.getData(),
                        Class.forName(resObjClass));
            }
            catch (JsonSyntaxException e)
            {
                LOGGER.error("", e);
                throw new ProtocolAdapterException("syncSendMessage error", e, 1);
            }
            catch (ClassNotFoundException e)
            {
                LOGGER.error("", e);
                throw new ProtocolAdapterException("syncSendMessage error", e, 1);
            }
            
            resBean.setDataBean(dataBean);
        }

        // interface log
        if (null != resBean)
        {
            String resultCode = String.valueOf(resBean.getSuccess());
            
            MessageContext mc = ThreadLocalHolder.get();
            if (null != mc)
            {
                String uuid = (String)mc.getEntities().get("interfaceLogger-TransactionId");
                InterfaceLogBean bean = new InterfaceLogBean();
                bean.setTransactionId(uuid);
                bean.setReq(false);
                bean.setRespTime(new Date());
                bean.setResultCode(resultCode);
                
                IInterfaceLog interfaceLogger = ApplicationContextUtil.getBean("interfaceLogger");
                interfaceLogger.info(bean);
            }
        }
        return resBean;
    }
}
